#include"ThreadPool.h"

ThreadPoll::ThreadPoll(size_t threadNum, const std::string &threadType): stop_(false), threadType_(threadType)
{
    // 启动 threadNum 个线程，每个线程都会阻塞在条件变量上
    for(size_t i = 0; i < threadNum; i++)
    {
        // 创建线程
        threads_.emplace_back([this]() {
            printf("create thread %s(%ld).\n", threadType_.c_str(), syscall(SYS_gettid));
            // 如果线程池还在运行中
            while(!stop_)
            {
                std::function<void()> task;
                // 取任务的操作对于每个线程来说只能同时有一个线程在处理
                {
                    // 开始加锁
                    std::unique_lock<std::mutex> lock(this->mutex_);
                    // 释放了 mutex_ 锁，但进行了 condition 的阻塞，等待唤醒
                    this->condition_.wait(lock, [this]() {
                        return (this->stop_ == true) || (this->taskQueue_.empty() == false);
                    });
                    // 如果线程池已经停止了，此时队列没任务了，那么就退出
                    if((this->stop_ == true) || (this->taskQueue_.empty() == true))
                    {
                        return;
                    }
                    // 否则就算线程池停止了，但是还有任务，那么也要执行完这个任务
                    // 出队一个任务
                    task = std::move(this->taskQueue_.front());
                    this->taskQueue_.pop();
                }
                printf("%s(%ld) execute task.\n", threadType_.c_str(), syscall(SYS_gettid));
                // 执行这个任务
                task();
            }
        });
    }
}

void ThreadPoll::AddTask(std::function<void()> task)
{
    {
        std::lock_guard<std::mutex> lock(mutex_);
        taskQueue_.push(task);
    }
    // 唤醒一个被 condition_ 阻塞的线程
    condition_.notify_one();
}

ThreadPoll::~ThreadPoll()
{
    // 标记线程池已经停止了，其他线程得到信息应该停止执行下一个任务了
    stop_ = true;
    // 唤醒全部的线程
    condition_.notify_all();
    // 等待全部线程执行完成后退出
    for(std::thread &th : threads_)
    {
        th.join();
    }
}